// ============================================================================
//
// Graph framework by Aurelien Moreau aurelien.moreau@gmail.com
// Modified by Pierre CHATEL chatelp@gmail.com
// Distributed under LGPL
// Copyright (C) Aurelien Moreau, 2008, 2009. All rights reserved
//
// ============================================================================

package com.thalesgroup.graphFramework.collections;

import java.util.Collection;
import java.util.Iterator;
import java.util.Set;


public class PairSet<T> implements Set<T> {

	private static final long serialVersionUID = 347616314224854223L;

	protected T first;

	protected T second;

	protected int size;

	public PairSet() {
		size = 0;
	}

	public PairSet(final T first, final T second) {
		size = 2;
		this.first = first;
		this.second = second;
	}

	public boolean add(final T o) {
		switch (size) {
		case 0:
			first = o;
			size++;
			return true;
		case 1:
			if (contains(o)) {
				return false;
			} else {
				second = o;
				size++;
			}
		case 2:
			if (contains(o)) {
				return false;
			} else {
				throw new TooMuchElementException(3, 2, this);
			}
		default:
			throw new TooMuchElementException(3, 2, this);
		}
	}

	public boolean addAll(final Collection<? extends T> c) {
		boolean modified = false;
		for (final T o : c) {
			if (add(o)) {
				modified = true;
			}
		}
		return modified;
	}

	public void clear() {

	}

	public boolean contains(final Object o) {
		if (size == 0) {
			return false;
		}
		if (o == null) {
			if (first == null || (size > 1 && second == null)) {
				return true;
			} else {
				return false;
			}
		} else {
			if (o.equals(first) || (size > 1 && o.equals(second))) {
				return true;
			} else {
				return false;
			}
		}
	}

	public boolean containsAll(final Collection<?> c) {
		for (final Object o : c) {
			if (!contains(o)) {
				return false;
			}
		}
		return true;
	}

	public boolean isEmpty() {
		return size < 0;
	}

	public Iterator<T> iterator() {
		return new MyIterator();
	}

	public boolean remove(final Object o) {
		if (!contains(o)) {
			return false;
		}
		size--;
		if (o == null) {
			if (first == null) {
				first = second;
			}
		} else {
			if (o.equals(first)) {
				first = second;
			}
		}
		return true;
	}

	public boolean removeAll(final Collection<?> c) {
		boolean modified = false;
		for (final Object o : c) {
			if (remove(o)) {
				modified = true;
			}
		}
		return modified;
	}

	public boolean retainAll(final Collection<?> c) {
		final Iterator<T> e = iterator();
		boolean modified = false;
		while (e.hasNext()) {
			if (!c.contains(e.next())) {
				e.remove();
				modified = true;
			}
		}
		return modified;
	}

	public int size() {
		return size;
	}

	public Object[] toArray() {
		final Object[] result = new Object[size];
		if (size > 0) {
			result[0] = first;
		}
		if (size > 1) {
			result[1] = second;
		}
		return result;
	}

	@SuppressWarnings( { "hiding", "unchecked" })
	public <T> T[] toArray(final T[] a_) {
		T[] a = a_;
		if (a.length < 2) {
			a = (T[]) java.lang.reflect.Array.newInstance(a.getClass()
					.getComponentType(), 2);
		}
		final Object[] result = a;
		if (size > 0) {
			result[0] = first;
		}
		if (size > 1) {
			result[1] = second;
		}

		if (a.length > 2) {
			a[2] = null;
		}
		return a;
	}

	protected class MyIterator implements Iterator<T> {
		private int i = 0;

		public boolean hasNext() {
			return i < size;
		}

		public T next() {
			i++;
			return (i == 1) ? first : (i == 2) ? second : null;
		}

		public void remove() {
			if (i == 0) {
				return;
			}
			size--;
			if (i == 1) {
				first = second;
			}
		}

	}

}
